package com.ericreboisson.client;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

public class Tree<T> {

	// NB: LinkedHashSet preserves insertion order
	private final Set<Tree> children = new LinkedHashSet<Tree>();
	private T data;
	private Object userObject;
	private Tree parent;

	public Tree(T data) {
		this.data = data;
	}

	public Tree child(T data) {
		for (Tree child : children) {
			if (child.data.equals(data)) {
				return child;
			}
		}

		return child(new Tree(data));
	}

	public Tree child(Tree<T> child) {
		child.parent = this;
		children.add(child);
		return child;
	}

	public Tree<T> recursiveSearch(T data) {
		if (this.data.equals(data))
			return this;
		Object[] children = this.getChildrenAsArray();
		Tree<T> res = null;
		for (int i = 0; res == null && i < children.length; i++) {
			res = ((Tree) children[i]).recursiveSearch(data);
		}
		return res;
	}

	public Set<Tree> getChildren() {
		return children;
	}

	public Object[] getChildrenAsArray() {
		return children.toArray();
	}

	public T getData() {
		return data;
	}

	public Object getUserObject() {
		return userObject;
	}

	public void setUserObject(Object userObject) {
		this.userObject = userObject;
	}
	
	public List<Tree> getPath() {
		List<Tree> path = new ArrayList<Tree>();
		Tree node = this;
		path.add(node);
		while(node.parent != null){
		  path.add(0,node.parent);
		  node = node.parent;
		}
		return path; //returns a path from {goal,...,root}
	}

	public static String join(List<Tree> path, String separator) {
	    StringBuilder sb = new StringBuilder();
	    String sep = "";
	    for(Tree tree: path) {
	        sb.append(sep).append(tree.getData());
	        sep = separator;
	    }
	    return sb.toString();                           
	}
	
}